/*
 *  Maildir.c
 *  MinimalSmtp
 *
 *  Created by Andrey on 27/12/2008.
 *  Copyright 2008 Karma Software. All rights reserved.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <string.h>
#include <sys/errno.h>

#include "Maildir.h"
#include "../ClientDispatch/ClientDispatchLog.h"

#define MAX_FILENAME_LENGTH 64
#define DEFAULT_FILE_MODE S_IRWXU | S_IRGRP | S_IROTH

int MaildirCreateForCurrentUser()
{
	if (mkdir(MAILDIR_ROOT, DEFAULT_FILE_MODE) == -1)
		printf("mkdir() failed with error %d\n", errno);
	
	if (mkdir(MAILDIR_ROOT "tmp", DEFAULT_FILE_MODE) == -1)
		printf("mkdir() failed with error %d\n", errno);
	
	if (mkdir(MAILDIR_ROOT "cur", DEFAULT_FILE_MODE) == -1)
		printf("mkdir() failed with error %d\n", errno);
	
	if (mkdir(MAILDIR_ROOT "new", DEFAULT_FILE_MODE) == -1)
		printf("mkdir() failed with error %d\n", errno);
	
	return 0;
}

int MaildirCreateStorage(AsciiStringPtr pathToStorage)
{
	int maxPathLength = strlen(pathToStorage) + 4 + 1;
	AsciiStringPtr storageSubdirectoryPath = 
	(AsciiStringPtr)malloc(maxPathLength);
	
	if (mkdir(pathToStorage, DEFAULT_FILE_MODE) == -1)
	{
		printf("mkdir() failed with error %d\n", errno);
		
		return errno;
	}
	
	snprintf(storageSubdirectoryPath, maxPathLength, "%s/tmp", pathToStorage);
	if (mkdir(storageSubdirectoryPath, DEFAULT_FILE_MODE) == -1)
	{
		printf("mkdir() failed with error %d\n", errno);
		
		return errno;
	}
	
	snprintf(storageSubdirectoryPath, maxPathLength, "%s/new", pathToStorage);
	if (mkdir(storageSubdirectoryPath, DEFAULT_FILE_MODE) == -1)
	{
		printf("mkdir() failed with error %d\n", errno);
		
		return errno;
	}
	
	snprintf(storageSubdirectoryPath, maxPathLength, "%s/cur", pathToStorage);
	if (mkdir(storageSubdirectoryPath, DEFAULT_FILE_MODE) == -1)
	{
		printf("mkdir() failed with error %d\n", errno);
		
		return errno;
	}
			
	return 0;
}

int MaildirStoreMessage(SmtpEnvelopePtr smtpEnvelope)
{
	struct stat fileInfo;
	int envelopeFile;
	AsciiChar tempFilename[MAX_FILENAME_LENGTH];
	AsciiChar envelopeFilename[MAX_FILENAME_LENGTH];
	struct timeval time;
		
	chdir(MAILDIR_ROOT);
	
	gettimeofday(&time, NULL);
	snprintf(tempFilename, MAX_FILENAME_LENGTH, "tmp/%d.%d.%d", time.tv_sec, getpid(), gethostid()); 
	
	while(stat(tempFilename, &fileInfo) != -1)
	{
		sleep(2);
		gettimeofday(&time, NULL);
		snprintf(tempFilename, MAX_FILENAME_LENGTH, "tmp/%d.%d.%d", time.tv_sec, getpid(), gethostid());
	}
	
	envelopeFile = open(tempFilename, O_CREAT | O_RDWR, DEFAULT_FILE_MODE);
	write(envelopeFile, smtpEnvelope->sender.localPart, strlen(smtpEnvelope->sender.localPart));
	write(envelopeFile, "@", 1);
	write(envelopeFile, smtpEnvelope->sender.domain, strlen(smtpEnvelope->sender.domain));
	write(envelopeFile, "\n", 1);
	for (int i = 0; i < smtpEnvelope->recipientCount; i++)
	{
		write(envelopeFile, 
			  smtpEnvelope->recipients[i].localPart, 
			  strlen(smtpEnvelope->recipients[i].localPart));
		write(envelopeFile, "@", 1);
		write(envelopeFile, 
			  smtpEnvelope->recipients[i].domain, 
			  strlen(smtpEnvelope->recipients[i].domain));
		write(envelopeFile, "\n", 1);
	}
	write(envelopeFile, smtpEnvelope->messageContents.data, smtpEnvelope->messageContents.dataLength);
	close(envelopeFile);
	
	snprintf(envelopeFilename, MAX_FILENAME_LENGTH, "new/%d.%d.%d", time.tv_sec, getpid(), gethostid());
	link(tempFilename, envelopeFilename);
	unlink(tempFilename);
	
	return 0;
}